package com.hyt.it.ogt.pj.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.StringUtils;
import com.hyt.it.ogt.pj.enums.CommonEnums;
import com.hyt.it.ogt.pj.enums.FileLocationEnum;
import com.hyt.it.ogt.pj.enums.SubjectiveItemTypeEnum;
import com.hyt.it.ogt.pj.enums.RejudgeEnums;
import com.hyt.it.ogt.pj.mapper.*;
import com.hyt.it.ogt.pj.model.entity.*;
import com.hyt.it.ogt.pj.model.vo.MarkDataVo;
import com.hyt.it.ogt.pj.model.vo.PaperItemVo;
import com.hyt.it.ogt.pj.model.vo.ResourceAttr;
import com.hyt.it.ogt.pj.service.IPaperItemFileService;
import com.hyt.it.ogt.pj.service.IPaperItemService;
import com.hyt.it.ogt.pj.service.IProjectDataDownLoadService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 题目表 服务实现类
 * </p>
 *
 * @author qiaozj
 * @since 2020-07-09
 */
@Service
public class PaperItemServiceImpl extends BaseServiceImpl<PaperItemMapper, PaperItem> implements IPaperItemService {

    @Autowired
    private IProjectDataDownLoadService iProjectDataDownLoadService;

    @Autowired
    private PaperItemMapper paperItemMapper;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private PieceScoreMapper pieceScoreMapper;

    @Autowired
    private ProjectSettingMapper projectSettingMapper;

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private ItemScoreMapper  itemScoreMapper;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private IPaperItemFileService paperItemFileService;

    @Override
    public List<PaperItemVo> selectMarkItem(String projectId, String subjectId, String paperId, String encodeId, String taskId) {
        List<PaperItemVo> paperItemVos = null;
        if (StringUtils.isEmpty(taskId)) {
            paperItemVos = paperItemMapper.selectMarkItem(projectId, subjectId, paperId, encodeId);
        } else {
            paperItemVos = paperItemMapper.selectSomeOneMarkItem(projectId, subjectId, paperId, encodeId, taskId);
        }
        List<PaperItemVo> children = new ArrayList<>();
        for (PaperItemVo paperItemVo : paperItemVos) {
            if (paperItemVo.getParentId() == null || "0".equals(paperItemVo.getParentId())) {
                if (!exists(children, paperItemVo)) {
                    children.add(paperItemVo);
                }
            }
        }
        children.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()));
        findChildren(children, paperItemVos);
        removeItem(children);
        return children;
    }


    /**
     * @Description: 去除非主观题，并设置大题总分
     * @author: longt
     * @Param: [paperItems]
     * @return: void
     * @date: 2022/3/24 下午12:25
     */
    private void removeItem(List<PaperItemVo> paperItems) {
        Iterator<PaperItemVo> iterator = paperItems.iterator();
        while (iterator.hasNext()) {
            PaperItemVo paperItemVo = iterator.next();
            List<PaperItemVo> children = paperItemVo.getChildren();
            Iterator<PaperItemVo> childIterator = children.iterator();
            boolean flag = false;
            while (childIterator.hasNext()) {
                PaperItemVo childPaperItemVo = childIterator.next();
                // 当itemViewPoint为false表示该题为主观题，存在主观题则不需要删除
                if (!childPaperItemVo.getItemViewPoint()) {
                    flag = true;
                } else {
                    childIterator.remove();
                }

                // 复合题情况
                if ("compound".equals(childPaperItemVo.getItemType())) {
                    Iterator<PaperItemVo> iteratorIterator = childPaperItemVo.getChildren().iterator();
                    boolean flag1 = false;
                    while (iteratorIterator.hasNext()) {
                        PaperItemVo paperItemVo1 = iteratorIterator.next();
                        if (!paperItemVo1.getItemViewPoint()) {
                            flag1 = true;
                        } else {
                            iteratorIterator.remove();
                        }
                    }
                    if (!flag1) {
                        childIterator.remove();
                    }
                }

            }

            // 一道主观题都没有
            if (!flag) {
                iterator.remove();
            }
        }
    }

    @Override
    public List<PaperItem> selectByPaperId(String paperId) {
        List<PaperItem> paperItems = paperItemMapper.selectByPaperId(paperId);
        return paperItems;
    }

    @Override
    public List<PaperItemVo> selectBlockList(String taskId, String projectId, String subjectId, String paperId, String encodeId, String userId) {
        List<PaperItemVo> paperItemVos = paperItemMapper.selectMarkItem2(taskId, projectId, subjectId, paperId, encodeId, userId);
        List<PaperItemVo> children = new ArrayList<>();

        for (PaperItemVo paperItemVo : paperItemVos) {
            if (paperItemVo.getParentId() == null || "0".equals(paperItemVo.getParentId())) {
                if (!exists(children, paperItemVo)) {
                    children.add(paperItemVo);
                }
            }
        }
        children.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()));
        findChildren(children, paperItemVos);
        removeItem(children);
        //设置分数
        children.forEach(paperItemVo -> {
            BigDecimal countScore = new BigDecimal("0");
            for (PaperItemVo item : paperItemVo.getChildren()) {
                if (item.getObtainScore() != null) {
                    countScore = countScore.add(item.getObtainScore());
                }
            }
            paperItemVo.setObtainScore(countScore);
        });

        // 设置题目中附件信息
        setPaperItemFileList(projectId, children);
        return children;
    }

    // 设置题目中附件信息
    private void setPaperItemFileList(String projectId, List<PaperItemVo> children) {
        // 设置附件信息
        List<PaperItemFile> paperItemFile  = paperItemFileService.lambdaQuery().eq(PaperItemFile::getProjectId, projectId).list();

        // 外层是大题
        for(PaperItemVo bigItem : children){
            List<PaperItemVo> paperItemVoList = bigItem.getChildren();
            if(CollectionUtils.isNotEmpty(paperItemVoList)){
                for(PaperItemVo paperItemVo : paperItemVoList) {
                    if(SubjectiveItemTypeEnum.compound.getCode().equals(paperItemVo.getItemType())
                            && CollectionUtils.isNotEmpty(paperItemVo.getChildren())){
                        List<PaperItemVo> childrenCompound= paperItemVo.getChildren();
                        childrenCompound.forEach(item ->{
                            setPaperItemFile(projectId, item, paperItemFile);
                        });
                    }
                    setPaperItemFile(projectId, paperItemVo, paperItemFile);
                }
            }
        }
    }

    // 设置附件信心
    private void setPaperItemFile(String projectId, PaperItemVo paperItemVo, List<PaperItemFile> paperItemFile){
        List<PaperItemFile> fileList = paperItemFile.stream().filter(item -> item.getItemId().equals(paperItemVo.getTopicId())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fileList)) {
            List<ResourceAttr> stemAttrs = new ArrayList<>();
            List<ResourceAttr> answerAttrs = new ArrayList<>();
            List<ResourceAttr> descriptionAttrs = new ArrayList<>();
            for (PaperItemFile item : fileList) {
                ResourceAttr resourceAttr = new ResourceAttr();
                resourceAttr.setOptionSort(item.getSort());
                resourceAttr.setFileType(item.getFileType());
                resourceAttr.setUrl(item.getUrl());
                if (FileLocationEnum.FILE_TYPE_STEM.getCode().equals(item.getFileLocation())) {
                    resourceAttr.setType(FileLocationEnum.FILE_TYPE_STEM.getCode());
                    stemAttrs.add(resourceAttr);
                    continue;
                }
                if (FileLocationEnum.FILE_TYPE_ANSWER.getCode().equals(item.getFileLocation())) {
                    resourceAttr.setType(FileLocationEnum.FILE_TYPE_ANSWER.getCode());
                    answerAttrs.add(resourceAttr);
                    continue;
                }
                if (FileLocationEnum.FILE_TYPE_DESCRIPTION.getCode().equals(item.getFileLocation())) {
                    resourceAttr.setType(FileLocationEnum.FILE_TYPE_DESCRIPTION.getCode());
                    descriptionAttrs.add(resourceAttr);
                    continue;
                }
            }
            paperItemVo.setStemAttrs(stemAttrs);
            paperItemVo.setAnswerAttrs(answerAttrs);
            paperItemVo.setDescriptionAttrs(descriptionAttrs);
        }
    }

    @Override
    public MarkDataVo selectPaperItemVoList(String projectId, String subjectId, String userId, String batchId, String placeId, String roomId) throws Exception {
        // 获取试卷id
        String paperId = paperMapper.getPaperIdByProjectIdAndSubject(projectId, subjectId);
        List<PaperItemVo> subjectivePaperItemTree = reSetPaperItemList(projectId, paperId);
        //没有需要评卷的题目
        if(CollectionUtils.isEmpty(subjectivePaperItemTree)){
            return  new MarkDataVo();
        }
        // 当前评卷人任务总人数
        int totalStu = pieceScoreMapper.countStudentByUserId(projectId, subjectId, userId, batchId, placeId, roomId);
        LambdaQueryWrapper<Task> taskQueryWrapper = new LambdaQueryWrapper<>();
        taskQueryWrapper.eq(Task :: getProjectId,projectId).eq(Task :: getSubjectId,subjectId);
        if(StringUtils.isNotEmpty(batchId)){
            taskQueryWrapper.eq(Task :: getBatchId,batchId);
        }
        if(StringUtils.isNotEmpty(placeId)){
            taskQueryWrapper.eq(Task :: getPlaceId,placeId);
        }
        if(StringUtils.isNotEmpty(roomId)){
            taskQueryWrapper.eq(Task :: getRoomId,roomId);
        }
        List<Task> tasks =  taskMapper.selectList(taskQueryWrapper);
        List<String> taskIds = tasks.stream().map(item -> item.getId()).collect(Collectors.toList());
        // 每一道主观题已评人数
        List<String> itemIds = subjectivePaperItemTree.stream().map(item -> item.getId()).collect(Collectors.toList());
        List<ItemScore> itemScores = itemScoreMapper.selectList(new LambdaQueryWrapper<ItemScore>().eq(ItemScore::getUserId, userId)
                .in(ItemScore::getItemId, itemIds).in(ItemScore ::getTaskId,taskIds));
        //查询task
        Map<String,Integer> taskMap = tasks.stream().collect(Collectors.toMap(Task::getId, Task::getAbsent, (key1, key2) -> key2));
        Map<String, Integer> itemfinishMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(itemScores)) {
            Map<String,List<ItemScore>> itemScoreMap = itemScores.stream().collect(Collectors.groupingBy(c -> c.getItemId()));
            for (Map.Entry<String, List<ItemScore>> entry : itemScoreMap.entrySet()) {
                int count = 0;
                for (ItemScore itemScore : entry.getValue()) {
                    if(null == itemScore.getFinish()){
                        continue;
                    }
                    if(CommonEnums.PIECCE_SCORE_FINSH_1.getCode().equals(itemScore.getFinish())){
                        count ++;
                    }else {
                        //缺席的需要加
                        if(MapUtils.isNotEmpty(taskMap) && CommonEnums.STUDENT_ABSENT_1.getCode().equals(taskMap.get(itemScore.getTaskId()) )){
                            count ++;
                        }
                    }

                }
                itemfinishMap.put(entry.getKey(), count);
            }
        }

        for(PaperItemVo itemVo : subjectivePaperItemTree){
            itemVo.setTotalStu(totalStu);
            itemVo.setProjectId(projectId);
            itemVo.setSubjectId(subjectId);
            itemVo.setFinishStu(0);
            if(itemfinishMap.containsKey(itemVo.getId())) {
                itemVo.setFinishStu(itemfinishMap.get(itemVo.getId()));
            }
        }

        // 设置内容
        MarkDataVo result = new MarkDataVo();

        // 封装
        List<PaperItemVo> parentsItem = paperItemMapper.selectParentItem(paperId);
        Map<String, PaperItemVo> collectMap = parentsItem.stream().collect(Collectors.toMap(PaperItemVo::getId, PaperItemVo -> PaperItemVo, (key1, key2) -> key2));
        Iterator<PaperItemVo> iterator = parentsItem.iterator();
        while (iterator.hasNext()) {
            PaperItemVo paperItemVo = iterator.next();
            List<PaperItemVo> children = new ArrayList<>();
            for(PaperItemVo itemVo : subjectivePaperItemTree){
                if(collectMap.get(itemVo.getBigItemId()) != null && paperItemVo.getId().equals(itemVo.getBigItemId())){
                    children.add(itemVo);
                }
            }
            paperItemVo.setChildren(children);
            if(CollectionUtils.isEmpty(children)){
                iterator.remove();
            }
        }
        result.setPaperItemVoList(parentsItem);

        // 设置附件信息列表
        setPaperItemFileList(projectId, parentsItem);

        // 设置项目相关返回值
        Project project = projectMapper.selectById(projectId);
        ProjectSetting projectSetting = projectSettingMapper.selectOne(new LambdaQueryWrapper<ProjectSetting>().eq(ProjectSetting::getProjectId, projectId));
        result.setProjectName(project.getTaskName());
        result.setRejudge(projectSetting.getRejudge());

        return result;
    }

    /**
     * 处理主观题列表
     */
    private List<PaperItemVo> reSetPaperItemList(String projectId, String paperId) throws Exception {
        List<PaperItemVo> subjectivePaperItems = iProjectDataDownLoadService.getSubjectivePaperItemTree(paperId);
        List<PaperItemVo> insertTemp = new ArrayList<>();

        // 把复合题里的主观题拿出来
        for(PaperItemVo item: subjectivePaperItems){
            if (SubjectiveItemTypeEnum.compound.getCode().equals(item.getItemType())) {
                List<PaperItemVo> children = item.getChildren();
                // parentId设置为大题的id
                for(PaperItemVo paperItemVo : children){
                    paperItemVo.setBigItemId(item.getParentId());
                }
                insertTemp.addAll(children);
            }else{
                item.setBigItemId(item.getParentId());
            }
        }

        // 合并题目
        subjectivePaperItems.addAll(insertTemp);

        // 删除复合题大题
        Iterator<PaperItemVo> iterator = subjectivePaperItems.iterator();
        while (iterator.hasNext()) {
            PaperItemVo item = iterator.next();
            if(SubjectiveItemTypeEnum.compound.getCode().equals(item.getItemType())){
                iterator.remove();
                continue;
            }
        }

        // 排序
        subjectivePaperItems = subjectivePaperItems.stream().sorted(Comparator.comparing(item -> item.getSubjectiveSort())).collect(Collectors.toList());

        // 重置题目的总数和序号
        setItemTotalIndex(subjectivePaperItems);

        // 设置附件信息列表
        List<PaperItemVo> tempBigItemtList = new ArrayList<>();
        PaperItemVo tempBigItem = new PaperItemVo();
        tempBigItem.setChildren(subjectivePaperItems);
        tempBigItemtList.add(tempBigItem);
        setPaperItemFileList(projectId, tempBigItemtList);

        int index = 1;
        for(PaperItemVo item: subjectivePaperItems){
            item.setSubjectiveSort(index);
            item.setNext(false);
            item.setPrevious(false);
            if(index > 1 && subjectivePaperItems.size() > 1){
                item.setPrevious(true);
            }
            if(index < subjectivePaperItems.size() && subjectivePaperItems.size() > 1){
                item.setNext(true);
            }
            if(item.isPrevious()){
                item.setPreviousItemId(subjectivePaperItems.get(index - 2) == null ? null : subjectivePaperItems.get(index - 2).getId());
            }
            if(item.isNext()){
                item.setNextItemId(subjectivePaperItems.get(index) == null ? null : subjectivePaperItems.get(index).getId());
            }
            PaperItem bigItem = findBigItem(BeanUtil.copyProperties(item, PaperItem.class));
            if(bigItem != null){
                item.setBigItem(bigItem.getOrderNum());
                item.setItemName(bigItem.getItemName());
            }
            index += 1;
        }

        logger.debug(JSONObject.toJSONString(subjectivePaperItems));
        // 按序号排序
        return subjectivePaperItems;
    }

    /**
     * 根据bigItemId获取获取totalIndex
     */
    private void setItemTotalIndex(List<PaperItemVo> subjectivePaperItems){
        Map<String, Integer> totalMap = new HashMap<>();
        Map<String, Integer> indexMap = new HashMap<>();
        int index = 0;
        for(PaperItemVo paperItemVo : subjectivePaperItems){
            if(null == totalMap.get(paperItemVo.getBigItemId())){
                totalMap.put(paperItemVo.getBigItemId(), 1);
                index = 1;
            }else {
                totalMap.put(paperItemVo.getBigItemId(), totalMap.get(paperItemVo.getBigItemId()) + 1);
                index += 1;
            }
            indexMap.put(paperItemVo.getId(), index);
        }
        // 设置
        for(PaperItemVo paperItemVo : subjectivePaperItems){
            paperItemVo.setItemTotal(totalMap.get(paperItemVo.getBigItemId()));
            paperItemVo.setItemIndex(indexMap.get(paperItemVo.getId()));
        }
    }

    /**
     * 找到大题
     * @param paperItem
     * @return
     */
    private PaperItem findBigItem(PaperItem paperItem){
        PaperItem parent = this.getById(paperItem.getParentId());
        if(!"0".equals(parent.getParentId())){
            return findBigItem(parent);
        }
        return parent;
    }


    @Override
    public PaperItemVo getCurrPaperItemInfo(String currUserId, String projectId, String subjectId, String itemId) throws Exception {
        // 当前题目信息
        PaperItemVo currentItemVo = paperItemMapper.selectProjectItem(currUserId, projectId, subjectId, itemId);
        List<PaperItemVo> paperItemVos = reSetPaperItemList(projectId, currentItemVo.getPaperId());
        currentItemVo = paperItemVos.stream().filter(item -> itemId.equals(item.getId())).findFirst().get();

        QueryWrapper<ProjectSetting> select = new QueryWrapper<>();
        select.lambda().eq(ProjectSetting::getProjectId, projectId);
        ProjectSetting projectSetting = projectSettingMapper.selectOne(select);
        currentItemVo.setRejudge(null == projectSetting ? RejudgeEnums.MARK_TYPE_UNALLOW_REVIEW.getCode() : projectSetting.getRejudge());
        //设置已评人数
        currentItemVo.setFinishStu(getStudentFinishStuNumer(currUserId,itemId));
        return currentItemVo;
    }



    @Override
    public BigDecimal getPaperSubjectiveScore(String projectId, String subjectId) {
        return paperItemMapper.getPaperSubjectiveScore(projectId, subjectId);
    }

    @Override
    public List<PaperItem> getPaperItemSubjective(String projectId, String subjectId) {
        return paperItemMapper.getPaperItemSubjective(projectId, subjectId);
    }

    private void findChildren(List<PaperItemVo> children, List<PaperItemVo> paperItemVos) {
        for (PaperItemVo paperItemVo : children) {
            List<PaperItemVo> child = new ArrayList<>();
            for (PaperItemVo itemVo : paperItemVos) {
                if (paperItemVo.getId() != null && paperItemVo.getId().equals(itemVo.getParentId())) {
                    if (!exists(child, itemVo)) {
                        child.add(itemVo);
                    }
                }
            }
            child.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()));
            paperItemVo.setChildren(child);
            findChildren(child, paperItemVos);
        }
    }

    private boolean exists(List<PaperItemVo> children, PaperItemVo paperItemVo) {
        boolean exist = false;
        for (PaperItemVo itemVo : children) {
            if (paperItemVo.getId().equals(itemVo.getId())) {
                exist = true;
            }
        }
        return exist;
    }


	@Override
	public Map<String, List<PaperItem>> selectAllObjectiveItemsByProjectIds(List<String> projectIds) {
		Map<String, List<PaperItem>> projectPaperItems = new HashMap<String, List<PaperItem>>();
		if (CollectionUtils.isEmpty(projectIds)) {
			return projectPaperItems;
		}
		// 首先查询所有的项目列表下的试卷
		Map<String, List<Paper>> projectPaperMaps = new HashMap<String, List<Paper>>();
		List<String> paperIds = new ArrayList<String>();
		List<Paper> papers = paperMapper.selectByProjectIds(projectIds);
		if (CollectionUtils.isNotEmpty(papers)) {
			for (Paper paper : papers) {
				paperIds.add(paper.getId());
				if (projectPaperMaps.containsKey(paper.getProjectId())) {
					List<Paper> projectPapers = projectPaperMaps.get(paper.getProjectId());
					projectPapers.add(paper);
					projectPaperMaps.put(paper.getProjectId(), projectPapers);
				} else {
					List<Paper> projectPapers = new ArrayList<Paper>();
					projectPapers.add(paper);
					projectPaperMaps.put(paper.getProjectId(), projectPapers);
				}
			}
		}
		if(CollectionUtils.isEmpty(paperIds)) {
			return projectPaperItems;
		}
		List<PaperItem> paperItems = paperItemMapper.selectAllObjectiveItemByPaperIds(paperIds);
		for (String projectId : projectPaperMaps.keySet()) {
			List<Paper> projectPapers = projectPaperMaps.get(projectId);
			List<PaperItem> projectPaperItemsTemp = new ArrayList<PaperItem>();
			for (Paper paper : projectPapers) {
				for (PaperItem paperItem : paperItems) {
					if (paperItem.getPaperId().equals(paper.getId())) {
						projectPaperItemsTemp.add(paperItem);
					}
				}
			}
			projectPaperItems.put(projectId, projectPaperItemsTemp);
		}
		return projectPaperItems;
	}


    @Override
    public Integer getStudentFinishStuNumer(String currUserId, String itemId) {
        QueryWrapper<ItemScore> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ItemScore::getItemId, itemId).eq(ItemScore::getUserId,currUserId);
        List<ItemScore> itemScores =  itemScoreMapper.selectList(queryWrapper);
        int count = 0;
        if(CollectionUtils.isEmpty(itemScores)){
            return count;
        }

        for (ItemScore itemScore :itemScores) {
            if(CommonEnums.PIECCE_SCORE_FINSH_1.getCode().equals(itemScore.getFinish())){
                count ++ ;
            }
        }

        return count;
    }
}
